﻿using Acornima.Ast;
using Jint;
using Jint.Runtime.Debugger;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using T.FAS.Runtime.Action.Service;
using T.FAS.Runtime.Action.SPI;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Base.Service;
using T.FAS.Runtime.Expression.Entity;
using T.FAS.Runtime.Expression.Service;
using T.FAS.Runtime.Expression.SGSPI;
using T.FAS.Runtime.Metadata.Client;
using T.FAS.Runtime.Metadata.Entity;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.Metadata.Entity.Page;
using T.ServiceComponent.Kernel.Service;

namespace T.FAS.Runtime.Expression.SGPlugin
{
    [SGService]
    public class QueryPlanSGService : IQueryPlanSGService
    {
        /// <summary>
        /// 执行方案查询
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, object> ExecuteQueryPlan(string queryPlanId, bool includeDetails)
        {
            Dictionary<string, object> res = new Dictionary<string, object>();
            try
            {
                TResult result = GetTResult(queryPlanId);
                if (result is TCommonResult<JObject> jobjectList)
                {
                    res.Add("state", "1");
                    res.Add("count", jobjectList.List.Count);
                    if (includeDetails)
                    {
                        res.Add("data", jobjectList.List);
                    }
                }
                else if (result is TCommonResult<TRecord> recordList)
                {
                    res.Add("state", "1");
                    res.Add("count", recordList.List.Count);
                    if (includeDetails)
                    {
                        res.Add("data", recordList.List);
                    }
                }
                else
                {
                    res.Add("state", "0");
                    res.Add("errmsg", $"查询方案{queryPlanId}获取数据失败!");
                    return res;
                }
            }
            catch (Exception e)
            {
                res.Add("state", "0");
                res.Add("errmsg", e.Message);
            }
            return res;
        }
        private TResult GetTResult(string queryPlanId)
        {
            var clientService = MetaDataClientService.GetInstance();
            List<ActionParameter> actionParameters = new List<ActionParameter>();
            QueryPlan queryPlan = new QueryPlanService().GetQueryPlanV2(queryPlanId);
            if (queryPlan == null)
                throw new ArgumentException($"{queryPlanId}查询方案不存在");
            PageMetaData pageMetaData = clientService.GetMetaData(queryPlan.PageID)?.Content as PageMetaData;
            if (pageMetaData == null)
                throw new ArgumentException($"{queryPlan.PageID}界面不存在");
            foreach (var item in pageMetaData.PCUIDom.Controls)
            {
                InitParam(actionParameters, item, queryPlan);
            }
            var metadata = clientService.GetMetaDataContent(queryPlan.DQID);
            TResult tResult;
            if (metadata is ActionMetaData)
            {
                tResult = ActionExecuteService.GetInstance.Execute(queryPlan.DQID, Action.SPI.ActionType.Action, actionParameters, false);
            }
            else if (metadata is DataQuery)
            {
                tResult = ActionExecuteService.GetInstance.Execute(queryPlan.DQID, Action.SPI.ActionType.DQ, actionParameters, false);
            }
            else
            {
                throw new ArgumentException($"{queryPlan.DQID}查询元数据不存在");
            }
            return tResult;
        }

        public void InitParam(List<ActionParameter> actionParameters, PageUIControl pageUIControl, QueryPlan queryPlan)
        {
            if (pageUIControl.CtrlType == "fas-advquery-1_1")
            {
                var options = JsonConvert.DeserializeObject<Dictionary<string, object>>(pageUIControl.Options);
                if (options?.ContainsKey("dataQuery") == true)
                {
                    var dataQuery = JsonConvert.DeserializeObject<Dictionary<string, object>>(JsonConvert.SerializeObject(options["dataQuery"]));

                    if (dataQuery?.ContainsKey("Parameters") == true)
                    {
                        var parameters = JsonConvert.DeserializeObject<List<ViewModelParameter>>(JsonConvert.SerializeObject(dataQuery["Parameters"]));
                        foreach (var item in parameters)
                        {
                            switch (item.Code)
                            {
                                case "PageIndex":
                                case "FasPageIndex":
                                    actionParameters.Add(new ActionParameter { ParameterName = item.Code, ParameterValue = 0 });
                                    break;
                                case "PageSize":
                                case "FasPageCount":
                                    actionParameters.Add(new ActionParameter { ParameterName = item.Code, ParameterValue = 10 });
                                    break;
                                case "AdvancedSort":
                                case "FasDynamicSort":
                                    actionParameters.Add(new ActionParameter { ParameterName = item.Code, ParameterValue = queryPlan.SortContent });
                                    break;
                                case "AdvancedFilter":
                                    if (queryPlan.FilterContent.Contains("@"))
                                    {
                                        Group group = JsonConvert.DeserializeObject<Group>(queryPlan.FilterContent);
                                        ExprService.GetInstance.TransformGroup(group);
                                        actionParameters.Add(new ActionParameter { ParameterName = item.Code, ParameterValue = JsonConvert.SerializeObject(group) });
                                    }
                                    else
                                    {
                                        actionParameters.Add(new ActionParameter { ParameterName = item.Code, ParameterValue = queryPlan.FilterContent });
                                    }
                                    break;
                                case "FasDynamicFilter":
                                    Group group2 = JsonConvert.DeserializeObject<Group>(queryPlan.FilterContent);
                                    if (queryPlan.FilterContent.Contains("@"))
                                    {
                                        ExprService.GetInstance.TransformGroup(group2);
                                    }
                                    actionParameters.Add(new ActionParameter { ParameterName = item.Code, ParameterValue = GetGroupExpr(group2) });
                                    break;
                                default:
                                    if (!string.IsNullOrEmpty(item.Value))
                                    {
                                        //var parser = new JavaScriptParser(item.Value);
                                        var script = Engine.PrepareScript(item.Value);
                                        NodeList<Statement> statements = script.Program.Body;
                                        if (statements.Count > 0 && statements[0] is ExpressionStatement statement)
                                        {
                                            if (statement.Expression is Literal literal)
                                            {
                                                actionParameters.Add(new ActionParameter { ParameterName = item.Code, ParameterValue = literal.Value });
                                            }
                                        }
                                    }
                                    break;
                            }
                        }
                    }
                }
            }
            else if (pageUIControl.Children.Count > 0)
            {
                foreach (var item in pageUIControl.Children)
                {
                    InitParam(actionParameters, item, queryPlan);
                }
            }
        }
        /// <summary>
        /// 根据高级查询获取可执行表达式
        /// </summary>
        /// <param name = "group"></param>
        /// <returns></returns>
        private Dictionary<string, object> GetGroupExpr(Group group)
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();
            if (group.Filters != null && group.Filters.Count > 0)
            {
                foreach (var item in group.Filters)
                {
                    if (item is Filter filter)
                    {
                        string[] codes = filter.Code.Split('.');
                        string code;
                        if (codes.Length == 0)
                            code = codes[0];
                        else
                            code = codes[1];
                        if (string.IsNullOrEmpty(code))
                            continue;
                        if (filter.Value.Count > 1)
                        {
                            dic.Add(code, JsonConvert.SerializeObject(filter.Value));
                        }
                        else
                        {
                            dic.Add(code, filter.Value[0]);
                        }
                    }
                }
            }
            return dic;
        }
    }
    /// <summary>
    /// Page查询方案入参
    /// </summary>
    [Serializable]
    public class ViewModelParameter
    {
        /// <summary>
        /// Code
        /// </summary>
        public string Code { get; set; }
        /// <summary>
        /// 形参名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 参数值
        /// </summary>
        public string Value { get; set; }
    }
}
